#include "udpServer.hpp"
#include <memory>
#include <fstream>
#include <unordered_map>
#include <signal.h>
using namespace Server;

static void Usage()
{
    cout << "Usage: 可执行程序 local_port" << endl;
}

const string dictAdd = "./dict.txt";
unordered_map<string, string> dict;

static bool cutString(const string &str, string *s1, string *s2, const string &seg)
{
    // hello:你好
    auto pos = str.find(seg);
    if (pos != string::npos)
    {
        *s1 = str.substr(0, pos);           //[ )
        *s2 = str.substr(pos + seg.size()); //[ )
        return true;
    }
    else
    {
        return false;
    }
}

// 初始化，加载字典dict.txt
static void initDict()
{
    // 打开文件
    ifstream in(dictAdd, ios::binary);
    if (!in.is_open())
    {
        cout << "open " << dictAdd << " error" << endl;
        exit(OPEN_ERR);
    }

    string line;
    string key, value;
    while (getline(in, line)) // 读取每一行
    {
        // 分割，放入map
        if (cutString(line, &key, &value, ":"))
            dict.insert(make_pair(key, value));
    }

    in.close();

    cout<<"字典加载成功"<<endl;
}

// demo1
void handlerMessage(int sockfd, string clientIp, uint16_t clientPort, string message)
{
    // cout << "   对数据: " << message << " 进行处理" << endl;
    string responce;

    auto it = dict.find(message);
    // unordered_map<string,string>::iterator it=dict.find(message);
    if (it == dict.end())
    {
        responce = "未收录";
    }
    else
    {
        responce = it->second;
    }

    struct sockaddr_in client_addr;
    bzero(&client_addr,sizeof(client_addr));

    client_addr.sin_family=AF_INET;
    client_addr.sin_port=htons(clientPort);
    client_addr.sin_addr.s_addr=inet_addr(clientIp.c_str());

    int n= sendto(sockfd, responce.c_str(), responce.size(), 0, (struct sockaddr*)&client_addr, sizeof(client_addr));
    if (n < 0)
    {
        cout << "sendto error: " << errno << ": " << strerror(errno) << endl;
        exit(SENDTO_ERR);
    }
}

// demo2
void execCommand(int sockfd, string clientIp, uint16_t clientPort, string cmd)
{
    if(cmd.find("rm")!=cmd.npos || cmd.find("mv")!=cmd.npos || cmd.find("rmdir")!=cmd.npos)
    {
        cout<<clientIp<<"["<<clientPort<<"]"<<"发送危险指令"<<endl;
        return;
    }

    string responce;
    char line[1024];

    FILE* fp=popen(cmd.c_str(),"r");
    if(fp==nullptr)
        responce=cmd + "执行失败";
    while(fgets(line,sizeof(line),fp))
    {
        responce += line;
    }
    pclose(fp);

    //返回执行结果
    struct sockaddr_in client_addr;
    bzero(&client_addr,sizeof(client_addr));

    client_addr.sin_family=AF_INET;
    client_addr.sin_port=htons(clientPort);
    client_addr.sin_addr.s_addr=inet_addr(clientIp.c_str());

    int n= sendto(sockfd, responce.c_str(), responce.size(), 0, (struct sockaddr*)&client_addr, sizeof(client_addr));
    if (n < 0)
    {
        cout << "sendto error: " << errno << ": " << strerror(errno) << endl;
        exit(SENDTO_ERR);
    }

}

void handler(int sig)
{
    (void)sig;
    initDict();
}

//  ./udpServer port
int main(int argc, char *argv[])
{

    if (argc != 2)
    {
        Usage();
        exit(USAGE_ERR);
    }

    uint16_t port = atoi(argv[1]); // 将字符串转化为int，uint16_t，只存2个低字节
    // string ip=argv[1];
    // unique_ptr<udpServer> usvr(new udpServer(port,ip));
    
    //initDict();
    //signal(2,handler);  //热加载字典，捕捉2号信号

    // unique_ptr<udpServer> usvr(new udpServer(handlerMessage, port));
    unique_ptr<udpServer> usvr(new udpServer(execCommand, port));

    usvr->initServer();
    usvr->start();
    return 0;
}


